#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linktab.h"
#define MAXLINE 128
#define PRIME 97 //用于制作哈希表
#define DATAFILE "./data/tongxunlu.csv"
typedef struct information
{
    char phone[12];
    char name[21];
    char remark[150];
    int status;
} Information;
Information inf[500];

LT_NODE *hash_by_phone[PRIME];
LT_NODE *hash_by_name[PRIME];

int open();
unsigned int BKDRHash(char *str);
void struct_swap(Information *px, Information *py);
int main()
{

    int choice;
    int temp_choice;                       //选项编号,case 2,3,4
    int number;                            //编号,case 3,4
    char name[21], phone[12], remark[150]; //临时信息,case 2,4
    int if_exist = 0;                      //判断是否存在,case 5,6
    char searchphone[12];                  //搜索时输入的手机号,case 5
    char searchname[21];                   //搜索时输入的姓名,case 6
    long phone_num;                        //转为long的手机号,case 5
    int hashvalue;                         //哈希值,case 5,6
    char *temp;                            //使用strtol函数时引入的临时指针,case 5
    int i, j;                              //循环变量
    LT_NODE *p;                            //用于遍历,case 5,6,9,0
    printf("1.打印通讯录\
            \n2.添加\
            \n3.删除\
            \n4.修改\
            \n5.按手机号查询\
            \n6.按姓名查询\
            \n7.按手机号排序\
            \n8.按姓名排序\
            \n9.打印手机号hashmap\
            \n0.打印姓名hashmap\n");
    scanf("%d", &choice);
    int linenum = open(); //打开文件并存入结构体
    //对手机号建立哈希表
    for (i = 0; i < PRIME; i++)
    {
        hash_by_phone[i] = (LT_NODE *)malloc(sizeof(LT_NODE)); //分配内存
        hash_by_phone[i]->data = i;
        hash_by_phone[i]->next = NULL; //初始化
    }
    for (i = 0; i < linenum; i++)
    {
        phone_num = strtol(inf[i].phone, &temp, 10);
        hashvalue = (int)(phone_num % PRIME);
        ListAppend(hash_by_phone[hashvalue], i);
    }
    //对姓名建立哈希表
    for (i = 0; i < PRIME; i++)
    {
        hash_by_name[i] = (LT_NODE *)malloc(sizeof(LT_NODE)); //分配内存
        hash_by_name[i]->data = i;
        hash_by_name[i]->next = NULL; //初始化
    }
    for (i = 0; i < linenum; i++)
    {
        hashvalue = (int)(BKDRHash(inf[i].name));
        ListAppend(hash_by_name[hashvalue], i);
    }

    switch (choice)
    {
    case 1:
    {
        printf("  姓名               电话              备注\n");
        printf("----------------------------------------------------\n");
        for (i = 0; i < linenum; i++)
        {
            printf("%s\t\t", inf[i].name);
            printf("%s\t\t", inf[i].phone);
            printf("%s\n", inf[i].remark);
        }
    }
    break;
    case 2:
    {
        printf("姓名:");
        scanf("%s", name);
        printf("电话:");
        scanf("%s", phone);
        printf("备注:");
        scanf("%s", remark);
        printf("是否保存？\n是:1,否:0\n");
        scanf("%d", &temp_choice);
        if (temp_choice)
        {
            strcpy(inf[linenum].name, name);
            strcpy(inf[linenum].phone, phone);
            strcpy(inf[linenum].remark, remark);
            inf[linenum].status = 1;
            FILE *fp = fopen(DATAFILE, "a,ccs=UTF-8");
            fprintf(fp, "%s,", inf[linenum].name);
            fprintf(fp, "%s,", inf[linenum].phone);
            fprintf(fp, "%s\n", inf[linenum].remark);
            linenum++;
            printf("添加成功！\n");
        }
    }
    break;
    case 3:
    {
        for (i = 0; i < linenum; i++)
        {
            printf("%d.", i + 1);
            printf("%s\t\t", inf[i].name);
            printf("%s\t\t", inf[i].phone);
            printf("%s\n", inf[i].remark);
        }
        printf("输入要删除的编号:");
        scanf("%d", &number);
        printf("确定删除？\n是:1,否:0\n");
        scanf("%d", &temp_choice);
        if (temp_choice)
        {
            inf[number - 1].status = 0;
            FILE *fp = fopen(DATAFILE, "w+,ccs=UTF-8");
            fprintf(fp, "%s,%s,%s\n", "姓名", "电话", "备注");
            for (i = 0; i < linenum; i++)
            {
                if (inf[i].status)
                {
                    fprintf(fp, "%s,", inf[i].name);
                    fprintf(fp, "%s,", inf[i].phone);
                    fprintf(fp, "%s\n", inf[i].remark);
                }
            }
            printf("已删除！\n");
        }
    }
    break;
    case 4:
    {
        for (i = 0; i < linenum; i++)
        {
            printf("%d.", i + 1);
            printf("%s\t\t", inf[i].name);
            printf("%s\t\t", inf[i].phone);
            printf("%s\n", inf[i].remark);
        }
        printf("输入要修改的编号:");
        scanf("%d", &number);
        printf("姓名:");
        scanf("%s", name);
        printf("电话:");
        scanf("%s", phone);
        printf("备注:");
        scanf("%s", remark);
        printf("是否保存更改？\n是:1,否:0\n");
        scanf("%d", &temp_choice);
        if (temp_choice)
        {
            strcpy(inf[number - 1].name, name);
            strcpy(inf[number - 1].phone, phone);
            strcpy(inf[number - 1].remark, remark);
            FILE *fp = fopen(DATAFILE, "w+,ccs=UTF-8");
            fprintf(fp, "%s,%s,%s\n", "姓名", "电话", "备注");
            for (i = 0; i < linenum; i++)
            {
                fprintf(fp, "%s,", inf[i].name);
                fprintf(fp, "%s,", inf[i].phone);
                fprintf(fp, "%s\n", inf[i].remark);
                //fprintf(fp, "%s\n", inf[i].if_delete);
            }
            printf("修改成功！\n");
        }
    }
    break;
    case 5:
    {
        printf("输入你要查找的手机号:");
        scanf("%s", searchphone);
        phone_num = strtol(searchphone, &temp, 10);
        hashvalue = (int)(phone_num % PRIME);
        p = hash_by_phone[hashvalue];
        p = p->next;
        while (p)
        {
            if (strcmp(searchphone, inf[p->data].phone) == 0)
            {
                printf("姓名:%s\n", inf[p->data].name);
                printf("电话:%s\n", inf[p->data].phone);
                printf("备注:%s\n", inf[p->data].remark);
                if_exist = 1;
                break;
            }
            p = p->next;
        }
        if (if_exist == 0)
            printf("不存在！\n");
    }
    break;
    case 6:
    {
        printf("输入你要查找的姓名:");
        scanf("%s", searchname);
        hashvalue = (int)BKDRHash(searchname);
        p = hash_by_name[hashvalue];
        p = p->next;
        while (p)
        {
            if (strcmp(searchname, inf[p->data].name) == 0)
            {
                printf("姓名:%s\n", inf[p->data].name);
                printf("电话:%s\n", inf[p->data].phone);
                printf("备注:%s\n", inf[p->data].remark);
                if_exist = 1;
                break;
            }
            p = p->next;
        }
        if (if_exist == 0)
            printf("不存在！\n");
    }
    break;
    case 7:
    {
        for (i = 0; i < linenum; i++)
        {
            for (j = 0; j < linenum - i - 1; j++)
            {
                if (strcmp(inf[j].phone, inf[j + 1].phone) > 0)
                    struct_swap(&inf[j], &inf[j + 1]);
            }
        }
        for (i = 0; i < linenum; i++)
        {
            printf("%s\t\t", inf[i].name);
            printf("%s\t\t", inf[i].phone);
            printf("%s\n", inf[i].remark);
        }
        //按手机号排序
    }
    break;
    case 8:
    {
         for (i = 0; i < linenum; i++)
        {
            for (j = 0; j < linenum - i - 1; j++)
            {
                if (strcmp(inf[j].name, inf[j + 1].name) > 0)
                    struct_swap(&inf[j], &inf[j + 1]);
            }
        }
        for (i = 0; i < linenum; i++)
        {
            printf("%s\t\t", inf[i].name);
            printf("%s\t\t", inf[i].phone);
            printf("%s\n", inf[i].remark);
        }
        //按姓名排序
    }
    break;
    case 9:
    {
        for (i = 0; i < PRIME; i++)
        {
            p = hash_by_phone[i];
            p = p->next;
            if (p)
                printf("哈希值为%d:\n", i);
            while (p)
            {
                printf("     编号:%d  电话:%s\n", p->data, inf[p->data].phone);
                p = p->next;
            }
        }
    }
    break;
    case 0:
    {
        for (i = 0; i < PRIME; i++)
        {
            p = hash_by_name[i];
            p = p->next;
            if (p)
                printf("哈希值为%d:\n", i);
            while (p)
            {
                printf("     编号:%d  姓名:%s\n", p->data, inf[p->data].name);
                p = p->next;
            }
        }
    }
    break;
    default:;
    }

    return 0;
}
int open() //打开文件，存入结构体并统计行数
{
    FILE *fp = NULL;
    char line[MAXLINE];
    fp = fopen(DATAFILE, "r+,ccs=UTF-8");
    if (fp == NULL)
    {
        printf("文件不存在！\n");
        exit(0);
    }
    int linenum = 0;
    char *p;
    fgets(line, MAXLINE, fp);
    while (fgets(line, MAXLINE, fp))
    {
        p = strtok(line, ",");
        strcpy(inf[linenum].name, p);
        p = strtok(NULL, ",");
        strcpy(inf[linenum].phone, p);
        p = strtok(NULL, "\n");
        strcpy(inf[linenum].remark, p);
        inf[linenum].status = 1;
        linenum++;
    }
    fclose(fp);
    return linenum;
}
unsigned int BKDRHash(char *str) //计算字符串的哈希值
{
    unsigned int seed = 131;
    unsigned int hash = 0;
    while (*str)
    {
        hash = hash * seed + (*str++);
    }
    return (hash % 97);
}
void struct_swap(Information *px, Information *py)
{
    Information temp;
    strcpy(temp.name, py->name);
    strcpy(py->name, px->name);
    strcpy(px->name, temp.name);
    strcpy(temp.phone, py->phone);
    strcpy(py->phone, px->phone);
    strcpy(px->phone, temp.phone);
    strcpy(temp.remark, py->remark);
    strcpy(py->remark, px->remark);
    strcpy(px->remark, temp.remark);
    int tempstatus;
    tempstatus = px->status;
    py->status = px->status;
    px->status = tempstatus;
}